AddCSLuaFile("cl_mapvote.lua")
AddCSLuaFile("shared.lua")

include("shared.lua")

util.AddNetworkString("RAM_MapVoteStart")
util.AddNetworkString("RAM_MapVoteUpdate")
util.AddNetworkString("RAM_MapVoteCancel")

MapVote.Continued = false

net.Receive("RAM_MapVoteUpdate", function(len, ply)
    if(MapVote.Allow) then
        if(IsValid(ply)) then
            local update_type = net.ReadUInt(3)
            
            if(update_type == MapVote.UPDATE_VOTE) then
                local map_id = net.ReadUInt(32)
                
                if(MapVote.CurrentMaps[map_id]) then
                    MapVote.Votes[ply:SteamID()] = map_id
                    
                    net.Start("RAM_MapVoteUpdate")
                        net.WriteUInt(MapVote.UPDATE_VOTE, 3)
                        net.WriteEntity(ply)
                        net.WriteUInt(map_id, 32)
                    net.Broadcast()
                end
            end
        end
    end
end)


function MapVote.Start(length, current, limit, prefix)
    current = current or MapVote.Config.AllowCurrentMap or false
    length = length or MapVote.Config.TimeLimit or 28
    limit = limit or MapVote.Config.MapLimit or 24

    local is_expression = false

    if not prefix then
        local info = file.Read(GAMEMODE.Folder.."/"..GAMEMODE.FolderName..".txt", "garrysmod")

        if(info) then
            local info = util.KeyValuesToTable(info)
            prefix = info.maps
        else
            error("MapVote Prefix can not be loaded from gamemode")
        end

        is_expression = true
    else
        if prefix and type(prefix) ~= "table" then
            prefix = {prefix}
        end
    end
    
    local maps = file.Find("maps/*.bsp", "garrysmod")
    
    local vote_maps = {}
    
    local amt = 0

    for k, map in RandomPairs(maps) do
        local mapstr = map:sub(1, -5):lower()
        if(not current and game.GetMap():lower()..".bsp" == map) then continue end

        if is_expression then
            if(string.find(map, prefix)) then -- This might work (from gamemode.txt)
                vote_maps[#vote_maps + 1] = map:sub(1, -5)
                amt = amt + 1
            end
        else
            for k, v in pairs(prefix) do
                if string.find(map, "^"..v) then
                    vote_maps[#vote_maps + 1] = map:sub(1, -5)
                    amt = amt + 1
                    break
                end
            end
        end
        
        if(limit and amt >= limit) then break end
    end
    
    net.Start("RAM_MapVoteStart")
        net.WriteUInt(#vote_maps, 32)
        
        for i = 1, #vote_maps do
            net.WriteString(vote_maps[i])
        end
        
        net.WriteUInt(length, 32)
    net.Broadcast()
    
    MapVote.Allow = true
    MapVote.CurrentMaps = vote_maps
    MapVote.Votes = {}
    
    timer.Create("RAM_MapVote", length, 1, function()
        MapVote.Allow = false
        local map_results = {}
        
        for k, v in pairs(MapVote.Votes) do
            if(not map_results[v]) then
                map_results[v] = 0
            end
            
            for k2, v2 in pairs(player.GetAll()) do
                if(v2:SteamID() == k) then
                    if(MapVote.HasExtraVotePower(v2)) then
                        map_results[v] = map_results[v] + 2
                    else
                        map_results[v] = map_results[v] + 1
                    end
                end
            end
            
        end
        
        local winner = table.GetWinningKey(map_results) or 1
        
        net.Start("RAM_MapVoteUpdate")
            net.WriteUInt(MapVote.UPDATE_WIN, 3)
            
            net.WriteUInt(winner, 32)
        net.Broadcast()
        
        local map = MapVote.CurrentMaps[winner]

        
        timer.Simple(4, function()
            hook.Run("MapVoteChange", map)
            RunConsoleCommand("changelevel", map)
        end)
    end)
end

function MapVote.Cancel()
    if MapVote.Allow then
        MapVote.Allow = false

        net.Start("RAM_MapVoteCancel")
        net.Broadcast()

        timer.Destroy("RAM_MapVote")
    end
end

----------------------------------------
----------------------------------------
----------------RTV SHIT----------------
----------------------------------------
----------------------------------------

local IsTTT = false
local Total_Votes = 0
local mt = FindMetaTable( "Player" )


local function tellall( text )

	if !text then return end

	for k,v in pairs( player.GetAll() ) do
		umsg.Start( "RTV_Msg", v )
			umsg.String( text )
		umsg.End()
	end

end

function mt:rtv_tell( text )

	if not text then return end

	umsg.Start( "RTV_Msg", self )
		umsg.String( text )
	umsg.End()

end

local function StartRTV( ply )

	if shouldvote then
		ply:rtv_tell( "You cannot vote to Rock the Vote at this time!" )
		return
	end

	if ply.Rocked then
		ply:rtv_tell( "You have already voted to Rock the Vote!" )
		return
	end

	ply.Rocked = true

	Total_Votes = Total_Votes + 1

	tellall( ply:Nick().." has voted to Rock the Vote! ("..math.Round( #player.GetAll() * 0.66 ) - Total_Votes.." needed)" )

	hook.Add("TTTEndRound", "EndRound_TTT", function() 
	if Total_Votes >= math.Round( #player.GetAll() * 0.66 ) then
		tellall( "A vote to change the map has started!" )
		MapVote.Start(30, false, 128, {"ttt_", "dm_", "cs_", "de_"} )
		end
	end)
end

concommand.Add( "rtv_start", StartRTV )

local function RemoveVotes( ply )

	if ply.Rocked then
		Total_Votes = Total_Votes - 1
	end

	timer.Simple( .5, function() -- We don't want to get the amount of players when the guy who's leaving is still here... lol
		if #player.GetAll() < 1 then return end
		if not shouldvote then
			if Total_Votes >= math.Round( #player.GetAll() * 0.66 ) then
				tellall( "A vote to change the map has started!" )
				MapVote.Start(30, false, 128, {"ttt_", "dm_", "cs_", "de_"} )   --StartRTV()
			end
		end
	end )

end
hook.Add( "PlayerDisconnected", "RTV_RemoveVotes", RemoveVotes )

local function RTV_Chat( ply, text )
	if #player.GetAll() <= 2 then return end --Makes it so you need 3 players in the server to RTV
	--tellall( "You need more players to RTV!" )
	local small = string.lower( text )

	if small == "!rtv" or small == "rtv" or small == "/rtv" then
		ply:ConCommand( "rtv_start" )
		return ""
	end

end
hook.Add( "PlayerSay", "RTV_PlayerSay", RTV_Chat )

